﻿using Authority.DataTransferObject.Routing;
using Authority.Doamin;
using Authority.Doamin.IRepository;
using Authority.Doamin.View;
using Authority.EFRepositoryImpl;
using Authority.IServices;
using Authority.IServices.Model.Routing;
using AutoMapper;
using HelperFromTheSkeleton.Convert;
using HelperFromTheSkeleton.Enums;
using HelperFromTheSkeleton.ExtendMethod;
using System.Reflection.PortableExecutable;

namespace Authority.ServiceImpl
{
    /// <summary>
    /// 路由权限服务
    /// </summary>
    public class RoutingAuthorityServiceImpl : IRoutingAuthorityService
    {
        private readonly IRoutingAuthorityRepository _routingAuthorityRepository;
        private readonly IRoutingCarryActionRepository _routingCarryActionRepository;
        private readonly ISubsystemRepository _subsystemRepository;
        private readonly IRoleAuthorityRoutingRepository _roleRoutingRepository;
        private readonly IMenuAuthorityRepository _menuAuthorityRepository;
        private readonly IUnitWork _unitWork;
        private readonly IMapper _mapper;

        public RoutingAuthorityServiceImpl(IUnitWork unitWork,
            IMapper mapper,
            IRoutingCarryActionRepository routingCarryActionRepository,
        IRoutingAuthorityRepository routingAuthorityRepository,
        ISubsystemRepository subsystemRepository,
        IMenuAuthorityRepository menuAuthorityRepository,
        IRoleAuthorityRoutingRepository roleAuthorityRoutingRepository
            )
        {
            _routingAuthorityRepository = routingAuthorityRepository;
            _routingCarryActionRepository = routingCarryActionRepository;
            _unitWork = unitWork;
            _mapper = mapper;
            _menuAuthorityRepository = menuAuthorityRepository;
            _roleRoutingRepository = roleAuthorityRoutingRepository;
            _subsystemRepository = subsystemRepository;
        }

        /// <summary>
        /// 新增路由权限
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task AddAsync(AddRoutingModel model)
        {
            if (string.IsNullOrEmpty(model.Code)) throw new InvalidOperationException("路由Code不能为空");
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("路由名称不能为空");
            if (model.SubsystemID == Guid.Empty) throw new InvalidOperationException("子系统ID不能为空");
            if (await _subsystemRepository.CountAsync(m => m.ID == model.SubsystemID) <= 0) throw new InvalidOperationException("无效的子系统");
            if (await _routingAuthorityRepository.CountAsync(m => (m.Name == model.Name || m.Code == model.Code) && m.SubsystemID == model.SubsystemID) > 0) throw new InvalidOperationException("子系统内的路由名称、编号不允许重复");
            RoutingAuthority dbInfo = new();
            model.CopyProperty(dbInfo);
            dbInfo.ID = Guid.NewGuid();
            _unitWork.Add(dbInfo);
            if (model.ActionIDs?.Count > 0)
            {
                model.ActionIDs.ForEach(m =>
                {
                    RoutingCarryAction routingCarryAction = new()
                    {
                        RoutingAuthorityID = dbInfo.ID,
                        ActionAuthorityID = m
                    };
                    _unitWork.Add(routingCarryAction);
                });
            }
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 修改路由权限
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task EditAsync(EditRoutingModel model)
        {
            if (string.IsNullOrEmpty(model.Code)) throw new InvalidOperationException("路由Code不能为空");
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("路由名称不能为空");
            if (model.ID == Guid.Empty) throw new InvalidOperationException("ID不能为空");
            RoutingAuthority dbInfo = await _routingAuthorityRepository.FirstAsync(m => m.ID == model.ID) ?? throw new InvalidOperationException("找不到此路由权限");
            if (await _routingAuthorityRepository.CountAsync(m => (m.Name == model.Name || m.Code == model.Code) && m.SubsystemID == dbInfo.SubsystemID && m.ID != model.ID) > 0) throw new InvalidOperationException("子系统内的路由名称、编号不允许重复");
            var subset = await _routingAuthorityRepository.GetAllSubsetAsync(model.ID);
            if (subset?.Count(m => m.ID == model.ParentID) > 0) throw new InvalidOperationException("设置的父级不能再自己的子集中");
            model.CopyProperty(dbInfo);
            _unitWork.Updata(dbInfo);
            var routingCarryAction = await _routingCarryActionRepository.FindAsync(m => m.RoutingAuthorityID == model.ID, null);
            routingCarryAction?.ForEach(m => _unitWork.Delete(m));
            if (model.ActionIDs?.Count > 0)
            {
                model.ActionIDs.ForEach(m =>
                {
                    RoutingCarryAction routingCarryAction = new()
                    {
                        RoutingAuthorityID = dbInfo.ID,
                        ActionAuthorityID = m
                    };
                    _unitWork.Add(routingCarryAction);
                });
            }
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task DeleteAsync(Guid id)
        {
            var dbInfo = await _routingAuthorityRepository.FirstAsync(m => m.ID == id) ?? throw new InvalidOperationException("找不到此路由权限");
            if (await _menuAuthorityRepository.CountAsync(m => m.RoutingAuthorityID == id) > 0) throw new InvalidOperationException("有菜单正在关联此路由");
            if (await _roleRoutingRepository.CountAsync(m => m.RoutingAuthorityID == id) > 0) throw new InvalidOperationException("有角色正在关联此路由");
            _unitWork.Delete(dbInfo);
            var routingCarryAction = await _routingCarryActionRepository.FindAsync(m => m.RoutingAuthorityID == id, null);
            routingCarryAction?.ForEach(m => _unitWork.Delete(m));
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<List<RoutingAuthorityDTO>> GetAsync(List<Guid> id)
        {
            List<RoutingView> dbInfo = await _routingAuthorityRepository.FindRoutingInfo(m => id.Contains(m.ID)) ?? throw new InvalidOperationException("找不到此路由权限");
            var result = _mapper.Map<List<RoutingAuthorityDTO>>(dbInfo);
            return result;
        }

        /// <summary>
        /// 获取一级
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public async Task<List<RoutingAuthorityListDTO>> GetOneLevelAsync(Guid? parentId)
        {
            List<RoutingAuthority> dbInfo = await _routingAuthorityRepository.FindAsync(m => m.ParentID == parentId, m => m.Name, OrderByEnum.Asc);
            var result = _mapper.Map<List<RoutingAuthorityListDTO>>(dbInfo);
            return result;
        }

        /// <summary>
        /// 获取树
        /// </summary>
        /// <returns></returns>
        public async Task<List<RoutingTreeDTO>> GetTreeAsync(Guid subsystemID)
        {
            List<RoutingView> dbInfo = await _routingAuthorityRepository.FindRoutingInfo(m => m.SubsystemID == subsystemID);
            var result = TreeConvert.EntityToTreeList<RoutingTreeDTO, RoutingView>(dbInfo);
            return result;
        }
    }

}